package Comp;

import IceAssembly.Check;
import IceAssembly.Table;
/**
 * The Comp Tokenize operations break a COMP string up into tokens that we can 
 * process easier than just a big long string.<br>
 * <u>Internal Variables Used:</u><p>
 * terminals: string of math characters which are not labels or numbers<br>
 * tokenized_string: string array of usable output for the evaluator and prefixer<br>
 * array_index: index of tokenized string that we are writing to<br>
 * pos: iterator of position of character to compare<br>
 * <p><b>Original Author:</b>  Peter
 */
public class Evaluate {
   Tokenize tokenize_instance = new Tokenize();
   Prefix prefix_instance = new Prefix();
   
    
   /**
    * Takes a string array in reverse polish notation and makes ICE2 instructions
    * for them, and makes the appropriate calls to have them assembled.
    * The parameter in will have been tokenized, processed, and converted to 
    * Reverse Polish Notation, so something like a+b in a math expression might 
    * be tokenized to a|+|b and then in RPN it might be +|a|b .
    * This operation will turn <b>+|a|b|</b> into:
    * <ul><li>STACK PUSHD b</li>
    * <li>STACK PUSHD a</li>
    * <li>SOPER ADD,2</li></ul>
    * Which could be further optimized, but in our jurisdiction is "good enough".
    * <p>
    * <b>Change Log:</b><br>
    * 05/05/08 - Initial Code - Peter Dietz<br>
    * 05/07/08 - change return to string array so process can call instructions.
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * none yet <br>
    * <p>
    * <b>Date of module being installed:</b> 05/05/08
    * <p><b>Original Author:</b>  Peter Dietz
    * @param rpn_string String array with the math prefixed in Reverse Polish Notation.
    * @return string array with an instruction at each point.
    */
    public String[] evaluatePrefix(String[] rpn_string, String equate_label){ 
        Check check_instance = new Check();                
        String[] instructions = new String[rpn_string.length+1];
        int inst_num = 0;
        int index = rpn_string.length-1;
        while(0 <= index){                       
            if(rpn_string[index].contains("+")){
                instructions[inst_num] = " SOPER ADD,2";
                inst_num++;
            } else if(rpn_string[index].contains("-")){
                instructions[inst_num] = " SOPER SUB,2";
                inst_num++;
            } else if(rpn_string[index].contains("*")){
                instructions[inst_num] = " SOPER MUL,2";
                inst_num++;
            } else if(rpn_string[index].contains("/")){
                instructions[inst_num] = " SOPER DIV,2";
                inst_num++;
            } else {                
                if(check_instance.isInt(rpn_string[index])==1){
                    if(rpn_string[index].length()>3){
                        instructions[-1]="";
                    }
                    if(Integer.parseInt(rpn_string[index])>511){
                        instructions[-1]="";
                    }
                    else{
                        instructions[inst_num] = " STACK PUSHD,I="+rpn_string[index];
                        inst_num++;
                    }
                }else{                    
                    if(check_instance.isValidLabel(rpn_string[index])==0){//not a valid label
                        instructions[-1]="";//invalid label comp ignored.
                    }else{
                        instructions[inst_num] = " STACK PUSHD,"+rpn_string[index];
                        inst_num++;
                    }
                }
            }
            index--;
        }
        
        if(check_instance.isInt(equate_label)==1){
            if(check_instance.isParameterOverflow(equate_label,"nmax")==1){
                instructions[-1]="";//parameter overflow comp ignored.
            }else{
                instructions[instructions.length-1] = " STACK POPD,"+equate_label;
                inst_num++;
            }
        }else{                    
            if(check_instance.isValidLabel(equate_label)==0){//not a valid label
                instructions[-1]="";//invalid label comp ignored.
            }else{
                Table table_instance = new Table();
                if(table_instance.isStartLabel(equate_label)==1){
                    instructions[-1]="";//invalid label comp ignored.
                }
                instructions[instructions.length-1] = " STACK POPD,"+equate_label;
                inst_num++;
            }
        }
        return instructions;
    }
    
        /**
    * This function returns the formula section of the operand for future processing.
    * <p>
    * <b>Change Log:</b><br>
     * 5/10/08 - Added Documentation - Keith Hill<br>
    * <br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * 161 - Operand invalid. Label Equated to zero. <br>
    * <p>
    * <b>Date of module being installed:</b> 5/8/08
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param pre_infix_array This is the operand that is passed to the function.
     * @param pos The position of the array.
         * @return Returns the forumla portion of the operand.
*/
    private String[] subStringArray(String[] pre_infix_array, int pos){
        String[] infix_array = new String[pre_infix_array.length-pos];
        for(int index=0; index<infix_array.length; index++){
            infix_array[index] = pre_infix_array[index+pos];
        }
        return infix_array;
    }
    
    /**
     * This function chops out blanks at th/e end of a string[].<p>
     * Modified Log:<br>
     * 5/10/08 - Edited Documentation - Keith Hill<br>
     * Error Condition tested: <br>
     * None<br>
     * <p>
     * Creation Date: May 7,2008.<br>
     * <p>
     * <b>Original Author:</b> Yogesh Jindal
     * @param pre_infix_array
     * @return Returns a String[] will no blanks at the end.
     */
    public String[] chopLastBlankIndexes(String[] pre_infix_array){
        int temp=-1;
        for(int index=0; index<pre_infix_array.length; index++){
            if(pre_infix_array[index].contentEquals("")){
                temp=index; 
                break;            
            }
        }
        if(temp==-1){
            return pre_infix_array;
        }else{
            String[] new_pre_infix_array = new String[temp];
            for(int index=0; index<new_pre_infix_array.length; index++){
                new_pre_infix_array[index] = pre_infix_array[index];
            }
            return new_pre_infix_array;
        }        
    }
    
    /**
     * This function removes all spaces from the operand string.
     * Modified Log:<p>
     * 5/10/08 - Fixed documentation - Keith Hill<br>
     * <p>
     * Error Condition tested:<br>
     * None<br>
     * <p>
     * Creation Date : May 7,2008.<br>
     * <b>Original Author:</b> Yogesh Jindal<br>
     * @param operand Any String with spaces.
     * @return Returns a new String with no blanks.
     */
    private String removeSpaces(String operand){
        for(int index=0; index<operand.length(); index++){
            operand = operand.replaceAll(" ", "");
            operand = operand.replaceAll("/t", "");
        }
        return operand;
    }
    
    /**
    * This function will remove spaces and break the string into multiple strings for processing.
    * <p>
    * <b>Change Log:</b><br>
    * 5/10/08 - Added Documentation - Keith Hill<br>
    * <p>
    * <b>Error Conditions Tested:</b><br>
    * None <br>
    * <p>
    * <b>Date of module being installed:</b> 5/06/08
    * <p><b>Original Author:</b>  Yogesh Jindal
    * @param operand The original input string from the user to be broken up.
    * @return The returned string array is composed of several substrings.
    */
    public String[] breakComp(String operand){        
        try{
            operand = removeSpaces(operand);            
            String[] pre_infix_array = tokenize_instance.tokenizeComp(operand);
            pre_infix_array = chopLastBlankIndexes(pre_infix_array);            
            //check some stuff here like =
            String[] infix_array = subStringArray(pre_infix_array, 2);            
            String prefix_string = prefix_instance.convToPrefix(infix_array);            
            String[] prefix_array = prefix_instance.preFixStringToArray(infix_array, prefix_string);            
            return evaluatePrefix(prefix_array,pre_infix_array[0]);
        }catch(Exception e){
            String[] error_string = new String[1];
            error_string[0]="wrong expression";
            return error_string;
        }
    }
}
